// Attributes (属性) 示例
program AttributesExample;

{$mode objfpc}{$H+}
{$M+} // 必须启用扩展RTTI支持

uses
  Classes, SysUtils, TypInfo;

// 定义一个简单的属性类
type
  TDescriptionAttribute = class(TCustomAttribute)
  private
    FDescription: string;
  public
    constructor Create(const ADescription: string);
    property Description: string read FDescription;
  end;

constructor TDescriptionAttribute.Create(const ADescription: string);
begin
  inherited Create;
  FDescription := ADescription;
end;

// 定义一个带多个参数的属性类
type
  TValidationAttribute = class(TCustomAttribute)
  private
    FMinValue, FMaxValue: Integer;
    FMessage: string;
  public
    constructor Create(AMinValue, AMaxValue: Integer; const AMessage: string);
    property MinValue: Integer read FMinValue;
    property MaxValue: Integer read FMaxValue;
    property Message: string read FMessage;
  end;

constructor TValidationAttribute.Create(AMinValue, AMaxValue: Integer; const AMessage: string);
begin
  inherited Create;
  FMinValue := AMinValue;
  FMaxValue := AMaxValue;
  FMessage := AMessage;
end;

// 使用属性标记类和字段
type
  [TDescription('表示一个人的信息')]
  TPerson = class
  private
    FName: string;
    FAge: Integer;
  public
    [TDescription('人的姓名')]
    property Name: string read FName write FName;
    
    [TDescription('人的年龄')]
    [TValidation(0, 150, '年龄必须在0到150之间')]
    property Age: Integer read FAge write FAge;
    
    [TDescription('获取人的信息摘要')]
    function GetInfo: string;
  end;

function TPerson.GetInfo: string;
begin
  Result := Format('姓名: %s, 年龄: %d', [Name, Age]);
end;

// 检查类型的属性信息
procedure CheckAttributes(AType: TClass);
var
  I: Integer;
  Attr: TCustomAttribute;
  DescriptionAttr: TDescriptionAttribute;
  PropList: PPropList;
  PropCount: Integer;
  PropInfo: PPropInfo;
begin
  WriteLn('检查类型: ', AType.ClassName);
  
  // 获取类型级别的属性
  WriteLn('  类型属性:');
  for I := 0 to AType.GetAttributes.Count - 1 do
  begin
    Attr := AType.GetAttributes[I];
    if Attr is TDescriptionAttribute then
    begin
      DescriptionAttr := TDescriptionAttribute(Attr);
      WriteLn('    描述: ', DescriptionAttr.Description);
    end;
  end;
  
  // 获取属性级别的属性
  WriteLn('  成员属性:');
  PropCount := GetPropList(AType, PropList);
  try
    for I := 0 to PropCount - 1 do
    begin
      PropInfo := PropList^[I];
      WriteLn('    属性: ', PropInfo^.Name);
      
      // 检查此属性上的属性
      // 注意：在实际应用中，这里需要更复杂的RTTI操作
    end;
  finally
    FreeMem(PropList);
  end;
  WriteLn;
end;

var
  Person: TPerson;

begin
  WriteLn('=== Pascal 属性示例 ===');
  WriteLn;
  
  // 创建实例
  Person := TPerson.Create;
  try
    Person.Name := '张三';
    Person.Age := 30;
    
    WriteLn('人员信息:');
    WriteLn('  ', Person.GetInfo());
    WriteLn;
    
    // 检查属性信息
    CheckAttributes(TPerson);
  finally
    Person.Free;
  end;
  
  WriteLn('属性示例完成。');
  ReadLn;
end.